﻿namespace Atomic.Plugins.Users.Data
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;

    using Atomic.Extensions;
    using Atomic.Data.AdoNet;
    using Atomic.Modules.Security;
    using Atomic.Core.Security;

    /// <summary>
    /// 用户仓储。
    /// </summary>
    public class UserRepository : RepositoryBase, IUserRepository
    {
        /// <summary>
        /// 表名。
        /// </summary>
        private const string TABLE_NAME = "atomic_u_users";

        /// <summary>
        /// 表主键。
        /// </summary>
        private const string TABLE_KEY = "Id";

        /// <summary>
        /// 创建一个用户。
        /// </summary>
        /// <param name="user">用户信息。</param>
        /// <param name="roles">角色编号列表。</param>
        /// <returns>是否成功。</returns>
        public bool Create(User user, string roles)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@Id", SqlDbType.BigInt),
                        new SqlParameter("@AccountNumber", SqlDbType.NVarChar, 20),
                        new SqlParameter("@Password", SqlDbType.NVarChar, 32),
                        new SqlParameter("@Name", SqlDbType.NVarChar, 50),
                        new SqlParameter("@Email", SqlDbType.NVarChar, 150),
                        new SqlParameter("@Roles", SqlDbType.NVarChar, 1000)
                    };

            parameters[0].Value = user.Id;
            parameters[1].Value = user.Account.AccountNumber;
            parameters[2].Value = user.Account.Password;
            parameters[3].Value = user.Name;
            parameters[4].Value = user.Email;
            parameters[5].Value = roles;

            string sql = "INSERT INTO " + TABLE_NAME + "(Id, AccountNumber, Password, Name, Email, Roles) VALUES (@Id, @AccountNumber, @Password, @Name, @Email, @Roles)";

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 是否存在该账号。
        /// </summary>
        /// <param name="accountNumber">账号。</param>
        /// <returns>存在返回 true，否则返回 false。</returns>
        public bool IsExistAccount(string accountNumber)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@AccountNumber", SqlDbType.NVarChar, 20)
                    };

            parameters[0].Value = accountNumber;

            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, "AccountNumber = @AccountNumber", parameters);
        }

        /// <summary>
        /// 是否存在该名称。
        /// </summary>
        /// <param name="name">用户名称。</param>
        /// <returns>存在返回 true，否则返回 false。</returns>
        public bool IsExistName(string name)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@Name", SqlDbType.NVarChar, 50)
                    };

            parameters[0].Value = name;

            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, "Name = @Name", parameters);
        }

        /// <summary>
        /// 是否已使用过该邮箱。
        /// </summary>
        /// <param name="email">邮箱地址。</param>
        /// <returns>使用过返回 true，否则返回 false。</returns>
        public bool IsUseEmail(string email)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@Email", SqlDbType.NVarChar, 150)
                    };

            parameters[0].Value = email;

            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, "Email = @Email", parameters);
        }

        /// <summary>
        /// 是否存在用户。
        /// </summary>
        /// <param name="id">用户标识。</param>
        /// <returns>存在返回 true，否则返回 false。</returns>
        public bool IsExistUser(long id)
        {
            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, TABLE_KEY + " = " + id);
        }

        /// <summary>
        /// 修改密码。
        /// </summary>
        /// <param name="id">用户标识。</param>
        /// <param name="password">新密码。</param>
        /// <returns>是否成功。</returns>
        public bool ChangePassword(long id, string password)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@Id", SqlDbType.BigInt),
                        new SqlParameter("@Password", SqlDbType.NVarChar, 32)
                    };

            parameters[0].Value = id;
            parameters[1].Value = password;

            string sql = "UPDATE " + TABLE_NAME + " SET Password = @Password WHERE Id = @Id";

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 创建一个用户。
        /// </summary>
        /// <param name="user">用户信息。</param>
        /// <param name="roles">角色编号列表。</param>
        /// <returns>是否成功。</returns>
        public bool Create(IUser user, string roles)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@AccountNumber", SqlDbType.NVarChar),
                        new SqlParameter("@Password", SqlDbType.NVarChar),
                        new SqlParameter("@Name", SqlDbType.NVarChar),
                        new SqlParameter("@Email", SqlDbType.NVarChar),
                        new SqlParameter("@Roles", SqlDbType.NVarChar)
                    };

            parameters[0].Value = user.Account.AccountNumber;
            parameters[1].Value = user.Account.Password;
            parameters[2].Value = user.Name;
            parameters[3].Value = user.Email;
            parameters[4].Value = roles;

            string sql = "INSERT INTO atomic_users([AccountNumber], [Password], [Name], [Email], [Roles]) VALUES (@AccountNumber, @Password, @Name, @Email, @Roles)";

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 获得用户详细信息。
        /// </summary>
        /// <param name="userId">用户编号。</param>
        /// <returns>用户详细信息。</returns>
        public UserDescriptor GetUser(int userId)
        {
            return this.GetUserByWhere(TABLE_KEY + " = " + userId);
        }

        /// <summary>
        /// 获得用户详细信息。
        /// </summary>
        /// <param name="accountNumber">用户账号。</param>
        /// <returns>用户详细信息。</returns>
        public UserDescriptor GetUser(string accountNumber)
        {
            return this.GetUserByWhere("AccountNumber = '" + accountNumber + "'");
        }

        /// <summary>
        /// 修改头像。
        /// </summary>
        /// <param name="userId">用户编号。</param>
        /// <param name="image">头像后缀名。</param>
        /// <returns>是否成功。</returns>
        public bool ChangeIcon(int userId, string image)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@Id", SqlDbType.Int),
                        new SqlParameter("@Image", SqlDbType.VarChar, 32)
                    };

            parameters[0].Value = userId;
            parameters[1].Value = image;

            string sql = "UPDATE " + TABLE_NAME + " SET Image = @Image WHERE Id = @Id";

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 获得用户详细信息。
        /// </summary>
        /// <param name="where">条件。</param>
        /// <returns>用户详细信息。</returns>
        private UserDescriptor GetUserByWhere(string where)
        {
            string sql = "SELECT " + TABLE_KEY + ", Name, Email, Image, Birthday, Sex, Description, RegisterTime, Disable FROM " + TABLE_NAME + (!string.IsNullOrWhiteSpace(where) ? " WHERE " + where : string.Empty);

            using (var dataReader = base.DataProvider.SqlQuery(sql))
            {
                UserDescriptor user = null;

                if (dataReader.Read())
                {
                    user = new UserDescriptor();
                    user.ChangeCurrentIdentity(dataReader.GetInt32(0));
                    user.Name = dataReader.GetString(1);
                    user.Email = dataReader.GetString(2);
                    user.Image = dataReader.GetString(3);
                    user.Birthday = dataReader.GetDateTime(4);
                    user.Sex = (Sex)dataReader.GetInt32(5);
                    user.Description = dataReader.GetString(6);
                    user.RegisterTime = dataReader.GetDateTime(7);
                    user.Disable = dataReader.GetInt32(8) == 0;
                }

                return user;
            }
        }
    }
}